<template>
<div  v-if="visible">
  <v-dialog
    width="80%"
    height="80%"
    :title="title"
   
    v-model="visible">
    <el-container  class="design">
    <el-container>
      <el-header class="dmHeader">
      <el-button-group>
        <el-tooltip class="item" effect="dark" content="保存并发布" placement="bottom"> 
          <el-button type="primary" @click="saveAndDeploy" icon="baocun" >保存并发布</el-button>
        </el-tooltip>
        <el-tooltip class="item" effect="dark" content="保存草稿" placement="bottom"> 
           <el-button type="primary" @click="save()" icon="baocun"> 保存草稿</el-button>
        </el-tooltip>
          <input type="file"  @change="showBPMN()"  id="btn_file" style="display:none">
       <el-tooltip class="item" effect="dark" content="打开流程文件" placement="bottom"> 
          <el-button type="primary"   @click="openLocal()" icon="folder-opened"> </el-button>
      </el-tooltip>
      <el-tooltip class="item" effect="dark" content="创建新的流程图" placement="bottom"> 
          <el-button type="primary"  @click="createNew" icon="CirclePlus"></el-button>
      </el-tooltip>
      <el-tooltip class="item" effect="dark" content="下载流程图" placement="bottom"> 
          <a class="el-button el-button--primary"  ref="saveSvg"  href="javascript:"><el-icon><Picture /></el-icon></a>
      </el-tooltip>
      <el-tooltip class="item" effect="dark" content="下载流程文件" placement="bottom"> 
          <a class="el-button el-button--primary"  ref="saveDiagram"  href="javascript:"><el-icon><Download /></el-icon></a>
      </el-tooltip>
      <el-tooltip class="item" effect="dark" content="撤销" placement="bottom"> 
          <el-button 
            @click="undo">
              <el-icon><RefreshLeft /></el-icon>
          </el-button>
      </el-tooltip>
      <el-tooltip class="item" effect="dark" content="恢复" placement="bottom">
          <el-button
            @click="redo">
             <el-icon><RefreshRight /></el-icon>
          </el-button>
      </el-tooltip>
      <el-tooltip class="item" effect="dark" content="放大" placement="bottom">
            <el-button
              
              @click="handleZoom(0.1)">
               <el-icon><ZoomIn /></el-icon>
            </el-button>
      </el-tooltip>
      <el-tooltip class="item" effect="dark" content="缩小" placement="bottom">
            <el-button
                
                @click="handleZoom(-0.1)" plain>
                 <el-icon><ZoomOut /></el-icon>
            </el-button>
      </el-tooltip>
      <el-tooltip class="item" effect="dark" content="重置" placement="bottom">
            <el-button @click="handleZoom(1)" plain>
               <el-icon><Rank /></el-icon>
            </el-button>
      </el-tooltip>
      </el-button-group>
        
      </el-header>
      <el-main class="dmMain">
         <div class="canvas" ref="canvas"></div>
      </el-main>
    </el-container>
        <el-aside  class="dmAside">
         <!-- <div id="js-properties-panel" class="panel"></div> -->
         <PaneRight
         ref="right"
        :element="toRaw2(element)"
        :bpmnModeler="bpmnModeler"
      />
      </el-aside>
  </el-container>
  </v-dialog>
</div>

</template>

<script>
// 引入相关的依赖
// import BpmnViewer from 'bpmn-js'
import {toRaw} from 'vue'
import BpmnModeler from 'jeeplus-bpmn/lib/Modeler'
// import customModule from './custom'
import PaneRight from './right/PaneRight.vue'
// import { operatorList } from './right/mock.js'
// 控制台工具
import CliModule from 'bpmn-js-cli'
import modelService from '@/api/flowable/modelService'
import appModelsService from '@/api/flowable/appModelsService'
import processService from '@/api/flowable/processService'
import taskDefExtensionService from '@/api/flowable/taskDefExtensionService'
import nodeSettingService from '@/api/flowable/nodeSettingService'
// import propertiesPanelModule from '@/components/bpmn-js-properties-panel'
// import propertiesProviderModule from '@/components/bpmn-js-properties-panel/lib/provider/camunda'
// import camundaModdleDescriptor from '@/components/camunda-bpmn-moddle/resources/camunda.json'
// import BpmnViewer from 'bpmn-js/lib/NavigatedViewer'

// import propertiesPanelModule from 'jp-bpmn-js-properties-panel'
import propertiesPanelModule from 'jp-bpmn-js-properties-panel'
import propertiesProvider from 'jp-bpmn-js-properties-panel/lib/provider/flowable'
import flowableModdleDescriptor from './flowable-bpmn-moddle/resources/flowable.json'
// import prioritiesModule from 'bpmn-js-task-priorities/lib/priorities'
// import bpmnJsInColorModule from 'bpmn-js-in-color'
import customTranslate from './customTranslate/customTranslate'
import { getBusinessObject } from 'jeeplus-bpmn/lib/util/ModelUtil'
import elementHelper from 'jp-bpmn-js-properties-panel/lib/helper/ElementHelper'
// import propertiesProviderModule from './properties-panel-extension/app/provider/magic'
// import magicModdleDescriptor from './properties-panel-extension/app/descriptors/magic'
import { is } from 'jeeplus-bpmn/lib/util/ModelUtil'
export default {
  name: 'designForm',
  data () {
    return {
      // bpmn建模器
      bpmnModeler: null,
      container: null,
      canvas: null,
      xmlStr: null,
      eventBus: null,
      processName: '',
      commandStack: null,
      modeling: null,
      modelId: '',
      category: '',
      currentConfig: undefined,
      activities: [],
      currentNode: undefined,
      element: null,
      visible: false,
      key_in_database: null,
      state: {
        scale: 1// 流程图比例
      }
    }
  },
  computed: {
    canUndo () {
      return this.commandStack ? this.commandStack.canUndo() : false
    },
    canRedo () {
      return this.commandStack ? this.commandStack.canRedo() : false
    },
    cli () {
      return window.cli
    }
  },
  props: {
    title: {
      type: String,
      default: 'JEEPLUS 流程设计器'
    }
  },
  components: {
    PaneRight
  },
  methods: {
    init (id, category) {
      this.element = null
      this.visible = true
      this.key_in_database = null
      if (category) {
        this.category = category
      } else {
        this.category = '未设置'
      }
      this.$nextTick(() => {
        this.createModel()
        if (id) {
          this.modelId = id
          modelService.getBpmnXml(id).then((data) => {
            this.createNewDiagram(data)
          })
        } else {
          this.modelId = null
          this.createNew()
        }
      })
    },
    updateProperty () {
      let obj = this.cli.element(this.currentNode.id)
      this.modeling.updateProperties(obj, { name: this.currentNode.name })
    },
    createModel () {
    // 获取到属性ref为“content”的dom节点
      this.container = this.$refs.content
    // 获取到属性ref为“canvas”的dom节点
      const canvas = this.$refs.canvas
      var customTranslateModule = {
        translate: [ 'value', customTranslate ]
      }
    // 建模，官方文档这里讲的很详细
      this.bpmnModeler = new BpmnModeler({
        container: canvas,
        keyboard: {
          bindTo: window
        },
      // 添加控制板
        // propertiesPanel: {
        //   parent: '#js-properties-panel'
        // },
        additionalModules: [
        // 左边工具栏以及节点
          propertiesProvider,
          // propertiesProviderModule,
        // 右边的工具栏
          propertiesPanelModule,
          customTranslateModule,
          // prioritiesModule,
          // customModule,
          CliModule
          // bpmnJsInColorModule
        ],
        cli: {
          bindTo: 'cli'
        },
        moddleExtensions: {
          flowable: flowableModdleDescriptor
          // magic: magicModdleDescriptor
        }
      })
      this.modeling = this.bpmnModeler.get('modeling')
      this.bpmnFactory = this.bpmnModeler.get('bpmnFactory')
      this.elementRegistry = this.bpmnModeler.get('elementRegistry')
      this.commandStack = this.bpmnModeler.get('commandStack')
      this.canvas = this.bpmnModeler.get('canvas')
      this.overlays = this.bpmnModeler.get('overlays')
      this.eventBus = this.bpmnModeler.get('eventBus')
      // var is = import('bpmn-js/lib/util/ModelUtil').is
      this.eventBus.on('element.click', 0, event => {
      // return false // will cancel event
        let el = event.element
        let node = el.businessObject
        this.currentNode = node
        this.element = el
        // if (is(el, 'bpmn:Process')) {
        //   let operator = operatorList.find(item => item.id === 9)
        //   if (operator) {
        //     this.currentConfig = operator
        //   } else {
        //     this.currentConfig = undefined
        //   }
        // }
        return true
      })

    // 下载画图
      let _this = this
    // 获取a标签dom节点
      const downloadLink = this.$refs.saveDiagram
      const downloadSvgLink = this.$refs.saveSvg
      this.commandStack = this.bpmnModeler.get('commandStack')
    // 给图绑定事件，当图有发生改变就会触发这个事件
      this.bpmnModeler.on('commandStack.changed', function () {
        _this.saveSVG(function (err, svg) {
          _this.setEncoded(downloadSvgLink, 'diagram.svg', err ? null : svg)
        })

        _this.saveDiagram(function (err, xml) {
          _this.setEncoded(downloadLink, 'diagram.bpmn', err ? null : xml)
        })
      })
    },
    createNewDiagram (bpmnXmlStr) {
      let _this = this
          // 获取a标签dom节点
      const downloadLink = this.$refs.saveDiagram
      const downloadSvgLink = this.$refs.saveSvg
      // 将字符串转换成图显示出来
      this.bpmnModeler.importXML(bpmnXmlStr, function (err) {
        _this.saveSVG(function (err, svg) {
          _this.setEncoded(downloadSvgLink, 'diagram.svg', err ? null : svg)
        })

        _this.saveDiagram(function (err, xml) {
          _this.setEncoded(downloadLink, 'diagram.bpmn', err ? null : xml)
        })
        if (err) {
          console.error(err)
        }
        if (_this.element === null) {
    // use RootElement of BPMN diagram to generate properties panel if no element is selected
          _this.element = _this.bpmnModeler.get('canvas').getRootElement()
          _this.key_in_database = _this.element.id
        }
      })
    },
    openLocal () {
      document.getElementById('btn_file').click()
    },
    createNew () {
      this.openDiagram('')
    },
    showBPMN () {
      var _this = this
      let file = document.getElementById('btn_file').files[0]
      var URL = window.URL || window.webkitURL
      var imgURL = URL.createObjectURL(file)
      var request = new XMLHttpRequest()
      request.open('GET', imgURL, true)
      request.onload = function () {
        if (request.status >= 200 && request.status < 400) {
        // Success!
          _this.openDiagram(request.responseText)
        } else {
        // We reached our target server, but it returned an error
        }
      }
      request.onerror = function () {
// There was a connection error of some sort
      }
      request.send()
    },
    openDiagram (bpmnXML) {
      if (bpmnXML === '' || bpmnXML === null) {
        let index = new Date().getTime()
        let index2 = new Date().getTime() + 56823
        bpmnXML = '<?xml version="1.0" encoding="UTF-8"?>' +
'<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:flowable="http://flowable.org/bpmn" id="sample-diagram" targetNamespace="http://www.flowable.org/processdef" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">' +
  '<bpmn2:process id="Process_' + index + '" name="流程_' + index + '">' +
    '<bpmn2:startEvent id="StartEvent_' + index2 + '" name="开始" flowable:initiator="applyUserId" />' +
  '</bpmn2:process>' +
  '<bpmndi:BPMNDiagram id="BPMNDiagram_1">' +
    '<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_' + index + '">' +
      '<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_' + index2 + '">' +
        '<dc:Bounds x="209" y="283" width="36" height="36" />' +
        '<bpmndi:BPMNLabel>' +
          '<dc:Bounds x="217" y="326" width="22" height="14" />' +
        '</bpmndi:BPMNLabel>' +
      '</bpmndi:BPMNShape>' +
    '</bpmndi:BPMNPlane>' +
  '</bpmndi:BPMNDiagram>' +
'</bpmn2:definitions>'
      }
      let _this = this
        // import diagram
      this.bpmnModeler.importXML(bpmnXML, function (err) {
        if (err) {
          console.error('could not import BPMN 2.0 diagram', err)
        }

    // use RootElement of BPMN diagram to generate properties panel if no element is selected
        _this.element = _this.bpmnModeler.get('canvas').getRootElement()
      })
    },
    save (deployFn) {
      const loading = this.$loading({
          lock: true,
          text: 'Loading',
          background: 'rgba(0, 0, 0, 0.7)'
        })
      let root = this.bpmnModeler.get('canvas').getRootElement().businessObject
      if (!this.modelId) {
        appModelsService.models({
            modelType: 0,
            key: root.id,
            name: root.name,
            description: root.documentation && root.documentation[0] && root.documentation[0].text ? root.documentation[0].text : ''
          }).then((data) => {
          this.modelId = data.id
          this.saveXML(deployFn)
        })
      } else {
        if (this.modelId && root.id !== this.key_in_database) {
          processService.exist(this.key_in_database).then((data) => {
            if (data === true) {
              this.$confirm('该流程已经发布, 你修改了流程id，将创建一个新流程, 是否继续?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
              }).then(() => {
                appModelsService.models({
                    modelType: 0,
                    key: root.id,
                    name: root.name,
                    description: root.documentation && root.documentation[0] && root.documentation[0].text ? root.documentation[0].text : ''
                  }).then((data) => {
                  this.modelId = data.id
                  this.saveXML(deployFn)
                })
              }).catch(() => {
                this.$message({
                  type: 'info',
                  message: '已取消'
                })
              })
            } else {
              this.saveXML(deployFn)
            }
          })
        } else {
          this.saveXML(deployFn)
        }
      }
    },
    saveXML (deployFn) {
      // eslint-disable-next-line handle-callback-err
      this.bpmnModeler.saveXML({ format: true }, (err, xml) => {
        const loading = this.$loading({
          lock: true,
          text: 'Loading',
          background: 'rgba(0, 0, 0, 0.7)'
        })
          let root = this.bpmnModeler.get('canvas').getRootElement().businessObject
          modelService.saveModel(this.modelId, {
            json_xml: xml,
            name: root.name,
            key: root.id,
            description: root.documentation && root.documentation[0] && root.documentation[0].text ? root.documentation[0].text : '',
            comment: '',
            lastUpdated: new Date().getTime()
          }).then((data) => {  
            if (data.id) {
              this.key_in_database = root.id
              this.saveExtension()
              if (deployFn) {
                // setTimeout(() => {
                  deployFn(this.modelId)
                // }, 2000)
              } else {
                this.$message.success('保存成功!')
                loading.close()
              }
              this.$emit('refreshList')
            } else {
              loading.close()
            }
          }).catch(()=>{
            loading.close()
          })
      })
    },
    calcElements(processDefId, flowElements, nodeSettingList, taskDefExtensionList, errorMsg){
      flowElements.forEach((flowElement) => {
        if (is(flowElement, 'bpmn:SubProcess')) {
          this.calcElements(processDefId, flowElement.flowElements, nodeSettingList, taskDefExtensionList, errorMsg)
        }
       if (is(flowElement, 'bpmn:UserTask') || is(flowElement, 'bpmn:SequenceFlow')) {
          let taskDefId = flowElement.id

          // 处理button
          let flowButtonList = []
          // 处理assginee
          let flowAssigneeList = []
          // 处理condition
          let flowConditionList = []

          if (flowElement.extensionElements && flowElement.extensionElements.values) {
            flowElement.extensionElements.values.forEach((element) => {
              if (is(element, 'flowable:Button')) {
                let obj = {code: element.code,
                  isHide: element.isHide,
                  id: '',
                  'taskDef.id': '',
                  name: element.name,
                  sort: element.sort,
                  next: element.next}
                flowButtonList.push(obj)
              }
              if (is(element, 'flowable:Assignee')) {
                let obj = {type: element.type,
                  value: element.value,
                  id: '',
                  'taskDef.id': '',
                  condition: element.condition,
                  sort: element.sort,
                  operationType: element.operationType}
                flowAssigneeList.push(obj)
              }
              if (is(element, 'flowable:Condition')) {
                let obj = {field: element.field,
                  compare: element.compare,
                  id: '',
                  'taskDef.id': '',
                  value: element.value,
                  sort: element.sort,
                  logic: element.logic}
                flowConditionList.push(obj)
              }
            })
             if (is(flowElement, 'bpmn:UserTask')) {
               if(flowAssigneeList.length === 0){
                 errorMsg.push(`节点【${flowElement.name || flowElement.id}】没有指定办理人。<br/>`)
               }
               if(flowButtonList.length === 0){
                  errorMsg.push(`节点【${flowElement.name || flowElement.id}】没有配置按钮。<br/>`)
               }
             }
            if ((flowAssigneeList.length > 0 ||  flowConditionList.length > 0 ||  flowButtonList.length > 0 ) && taskDefId) {
              taskDefExtensionList.push( {processDefId: processDefId, taskDefId: taskDefId, flowButtonList: flowButtonList, flowConditionList:flowConditionList, flowAssigneeList: flowAssigneeList})
            }
          }else{
            if (is(flowElement, 'bpmn:UserTask')) {
             errorMsg.push(`节点【${flowElement.name || flowElement.id}】没有指定办理人。<br/>`)
             errorMsg.push(`节点【${flowElement.name || flowElement.id}】没有配置按钮。<br/>`)
            }
          }
        }
      if ((is(flowElement, 'bpmn:StartEvent') && !is(flowElement.$parent, 'bpmn:SubProcess')) || is(flowElement, 'bpmn:UserTask')) {
          let taskDefId = flowElement.id
          var bo = getBusinessObject(flowElement)
          let formReadOnly = bo.get('flowable:formReadOnly')
          let formType = bo.get('flowable:formType')
          if(!bo.get('flowable:formKey')){
              errorMsg.push(`节点【${flowElement.name || flowElement.id}】没有配置表单。<br/>`)
          }
          if (taskDefId) {
            nodeSettingList.push({processDefId: processDefId, taskDefId: taskDefId, key: 'formReadOnly', value: formReadOnly})
            nodeSettingList.push({processDefId: processDefId, taskDefId: taskDefId, key: 'formType', value: formType})
          }
        }
      if (is(flowElement, 'bpmn:SequenceFlow')) {
          let taskDefId = flowElement.id
          var bo = getBusinessObject(flowElement)
          let conditionType = bo.get('flowable:conditionType')
          if (conditionType) {
            nodeSettingList.push({processDefId: processDefId, taskDefId: taskDefId, key: 'conditionType', value: conditionType})
          }
        }
      })
    },
    saveExtension () {
      let root = this.bpmnModeler.get('canvas').getRootElement().businessObject
      let processDefId = root.id
      let nodeSettingList = []
      let taskDefExtensionList = []
      let errorMsg = []
      this.calcElements(processDefId, root.flowElements, nodeSettingList, taskDefExtensionList, errorMsg)
      taskDefExtensionService.save(JSON.stringify(taskDefExtensionList))
      nodeSettingService.save(JSON.stringify(nodeSettingList))
      if(errorMsg.length> 0){
        this.$notify({
          title: '提示',
          type: 'warning',
          dangerouslyUseHTMLString: true,
          message: errorMsg.join(''),
          duration: 20000
        });
      }
    },
    saveAndDeploy () {
      this.$confirm(`确认要保存并发布流程吗?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.save(this.deploy)
      })
    },
          // 部署
    deploy (id) {
      const loading = this.$loading({
        lock: true,
        text: 'Loading',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      })
      modelService.deploy({id: id, category: this.category}).then((data) => {
        this.$message.success({dangerouslyUseHTMLString: true,
          message: data})
        this.$emit('refreshList')
        loading.close()
      }).catch(()=>{
        loading.close()
      })
    },
    toRaw2 (ele) {
      return toRaw(ele)
    },
    // 下载为SVG格式,done是个函数，调用的时候传入的
    saveSVG (done) {
      // 把传入的done再传给bpmn原型的saveSVG函数调用
      this.bpmnModeler.saveSVG(done)
    },
    // 下载为SVG格式,done是个函数，调用的时候传入的
    saveDiagram (done) {
      // 把传入的done再传给bpmn原型的saveXML函数调用
      this.bpmnModeler.saveXML({ format: true }, function (err, xml) {
        done(err, xml)
      })
    },
    // 当图发生改变的时候会调用这个函数，这个data就是图的xml
    setEncoded (link, name, data) {
      // 把xml转换为URI，下载要用到的
      const encodedData = encodeURIComponent(data)
      // 获取到图的xml，保存就是把这个xml提交给后台
      this.xmlStr = data
      // 下载图的具体操作,改变a的属性，className令a标签可点击，href令能下载，download是下载的文件的名字
      if (data) {
        // link.className = 'active'
        link.href = 'data:application/bpmn20-xml;charset=UTF-8,' + encodedData
        link.download = name
      }
    },
    undo () {
      window.cli.undo()
    },
    redo () {
      window.cli.redo()
    },
        // 流程图放大缩小
    handleZoom (radio) {
      // const newScale = !radio
      //       ? 1.0 // 不输入radio则还原
      //       : this.state.scale + radio <= 0.2 // 最小缩小倍数
      //       ? 0.2
      //       : this.state.scale + radio
      if (radio === 1) {
        this.state.scale = 1
      } else if ((this.state.scale > 0.2 && radio === -0.1) || (this.state.scale < 2 && radio === 0.1)) {
        this.state.scale = this.state.scale + radio
      }

      this.bpmnModeler.get('canvas').zoom(this.state.scale)
    }
  }
}
</script>


<style lang="scss">
  /*左边工具栏以及编辑节点的样式*/
  @import 'bpmn-js/dist/assets/diagram-js.css';
  @import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
  @import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css';
  @import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css';
  /*右边工具栏样式*/
  @import 'jp-bpmn-js-properties-panel/dist/assets/bpmn-js-properties-panel.css';

  .dmHeader {
    border-top: 1px solid #e7eaec;
    border-bottom: 1px solid #e7eaec;
    background-color: #f8f8f8;
    text-align: left;
    line-height: 50px !important;
    height: 50px !important;
  }
  
  .dmAside {
    border: 1px solid #e7eaec;
    background-color: #f8f8f8;
    width: 500px !important;
  }
  .dmMain {
    padding: 10px !important;
  }
  .canvas{
    width: 100%;
    height:700px;
  }

.design  {
    color: #606266;
    font-size: 14px;
    word-break: break-all;
    border: 1px solid #6062662b;
}

  .font{
    padding: 0;
    outline: none;
    cursor: pointer;
    font-size: 22px;
    color: #555555;
    background: none;
    border: none;
  }
  .djs-container svg{
    left:80px
  }
  .djs-palette{
    left: 0px;
    top: 0px;
  }

  rect{
    position: absolute;
    background-color: #fff;
    border: #a8a8a8 solid 1px;
    border-radius: 10px;
    box-shadow: 2px 2px 19px #e0e0e0;
    margin: 0;
    padding-left: 48px;
    cursor: default;
    display: table;
  }

  // .panel{
  //   position: absolute;
  //   right: 0px;
  //   top: 0;
  //   width: 500px;
  // }
  .buttons{
    &>li{
      display:inline-block;margin: 0px;
      &>a{
        color: #999;
        background: #eee;
        cursor: not-allowed;
        padding: 8px;
        border: 1px solid #ccc;
        &.active{
          color: #333;
          background: #fff;
          cursor: pointer;
        }
      }
    }
  }


  .djs-drag-active.hover.new-parent, .djs-container svg{
    background: url("") repeat !important;
  }
  .djs-hit{
    // r: 8;
    fill: '270-#fff-#d7d7d7';
    stroke: '#ccc';
    stroke-width: 1;
    // stroke-width-active: 2;
    // 'stroke-active': '#0099cc';
  }

// circle, rect, polygon, g {
//     stroke: #b3d8ff !important;
//     cursor: default;
//     display: table;
// }
</style>
